﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;

namespace Barcode
{
    enum InputMode { Default, Barcode };

    public class BarcodeEventArgs : EventArgs
    {
        private string data;

        public BarcodeEventArgs(string barcodeData)
        {
            data = barcodeData;
        }

        public string Data
        {
            get { return data; }
            set { data = value; }
        }
    }

    public class BarcodeCharEventArgs : EventArgs
    {
        private string data;

        public BarcodeCharEventArgs( string ReadChar )
        {
            data = ReadChar;
        }

        public string Char
        {
            get { return data; }
            set { data = value; }
        }
    }

    public class BarcodeReader
    {
        CommandBinding cb = null;
        InputMode Mode = InputMode.Default;
        string bar = "";
        public event EventHandler<BarcodeEventArgs> BarcodeEvent;
        public event EventHandler<BarcodeCharEventArgs> BarcodeCharEvent;

        public static List<string> Log { get; set; }

        public void Start(UIElement control)
        {
            Log = new List<string>();
            Log.Add("Start Barcode");
            Mode = InputMode.Default;
            bar = "";

            Keyboard.AddPreviewKeyDownHandler(control, keyhandler);

            KeyGesture g = new KeyGesture(Key.B, ModifierKeys.Control | ModifierKeys.Shift, "Ctrl+Shift+B");
            RoutedCommand rc = new RoutedCommand();
            rc.InputGestures.Add(g);
            cb = new CommandBinding(rc);
            cb.Executed += new ExecutedRoutedEventHandler(cb_Executed);
            control.CommandBindings.Add(cb);
        }

        public void Stop(UIElement control)
        {
            Keyboard.RemovePreviewKeyDownHandler(control, keyhandler);
            control.CommandBindings.Remove(cb);
        }

        void cb_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            log("START");
            Mode = InputMode.Barcode;
            bar = "";
        }

        void log( string s )
        {
            if (BarcodeCharEvent != null)
                BarcodeCharEvent(this, new BarcodeCharEventArgs(s));
        }

        void keyhandler(object sender, KeyEventArgs e)
        {

            log( " KEY " + e.Key.ToString() );
            if (Mode > 0)
            {

                Key k = e.Key;
                k = MapKey(e.Key);
                e.Handled = true;
                if (k == Key.Enter)
                {
                    log("Enter");
                    Mode = InputMode.Default;
                    string b = bar;
                    bar = "";
                    EventHandler<BarcodeEventArgs> temp = BarcodeEvent;
                    if (temp != null)
                        temp(this, new BarcodeEventArgs(b));
                }
                else
                    if (k != Key.None)
                    {
                        KeyConverter kc = new KeyConverter();
                        string s = kc.ConvertToString(k).ToString();
                        bar += s;
                        log("Bar = " + bar);
                    }
            }
        }

        private Key MapKey(Key key)
        {
            Dictionary<Key, Key> maps = new Dictionary<Key, Key>
            {
                { Key.NumPad0, Key.D0 },
                { Key.NumPad1, Key.D1 },
                { Key.NumPad2, Key.D2 },
                { Key.NumPad3, Key.D3 },
                { Key.NumPad4, Key.D4 },
                { Key.NumPad5, Key.D5 },
                { Key.NumPad6, Key.D6 },
                { Key.NumPad7, Key.D7 },
                { Key.NumPad8, Key.D8 },
                { Key.NumPad9, Key.D9 }
            };
            List<Key> allowed = new List<Key>
            {
                Key.Enter,
                Key.A, Key.B, Key.C, Key.D, Key.E, Key.F, Key.G, Key.H, Key.I, Key.J,
                Key.K, Key.L, Key.M, Key.N, Key.O, Key.P, Key.Q, Key.R, Key.S, Key.T,
                Key.U, Key.V, Key.W, Key.X, Key.Y, Key.Z,
                Key.D0, Key.D1, Key.D2, Key.D3, Key.D4, Key.D5, Key.D6, Key.D7, Key.D8, Key.D9
            };

            Key k = Key.None;
            if (maps.ContainsKey(key))
                key = maps[key];
            if (allowed.Contains(key))
                k = key;
            return k;
        }

    }
}
